import { 
  IEquation, 
  IEquationPosition, 
  BalanceResult 
} from '../types/chemistry'
import { EquationPositions } from './chemistry'

// 化学方程式类
export class Equation implements IEquation {
  private _left: EquationPositions = new EquationPositions();
  private _right: EquationPositions = new EquationPositions();

  appendLeft(position: IEquationPosition): void {
    this._left.append(position as any);
  }

  appendRight(position: IEquationPosition): void {
    this._right.append(position as any);
  }

  balance(): boolean {
    const result = this.balanceEquation();
    return result.success;
  }

  // 获取详细的平衡结果
  getBalanceResult(): BalanceResult {
    return this.balanceEquation();
  }

  private balanceEquation(): BalanceResult {
    const MAX_COEFF = 10;
    const leftSize = this._left.getFormulasCount();
    const rightSize = this._right.getFormulasCount();

    if (leftSize === 0 || rightSize === 0) {
      return {
        success: false,
        message: '方程式两边都必须有化合物'
      };
    }

    const leftCoeffs: number[] = new Array(leftSize).fill(1);
    const rightCoeffs: number[] = new Array(rightSize).fill(1);

    const success = this.tryBalance(leftCoeffs, rightCoeffs, 0, 0, MAX_COEFF);
    
    if (success) {
      return {
        success: true,
        equation: this.print(),
        leftCoeffs: [...leftCoeffs],
        rightCoeffs: [...rightCoeffs],
        message: '配平成功！'
      };
    } else {
      return {
        success: false,
        message: `无法在系数范围1-${MAX_COEFF}内配平此方程式`
      };
    }
  }

  private tryBalance(
    leftCoeffs: number[], 
    rightCoeffs: number[], 
    leftIndex: number, 
    rightIndex: number, 
    maxCoeff: number
  ): boolean {
    if (leftIndex === leftCoeffs.length && rightIndex === rightCoeffs.length) {
      return this.checkBalance(leftCoeffs, rightCoeffs);
    }

    if (leftIndex < leftCoeffs.length) {
      for (let i = 1; i <= maxCoeff; i++) {
        leftCoeffs[leftIndex] = i;
        if (this.tryBalance(leftCoeffs, rightCoeffs, leftIndex + 1, rightIndex, maxCoeff)) {
          return true;
        }
      }
    } else if (rightIndex < rightCoeffs.length) {
      for (let i = 1; i <= maxCoeff; i++) {
        rightCoeffs[rightIndex] = i;
        if (this.tryBalance(leftCoeffs, rightCoeffs, leftIndex, rightIndex + 1, maxCoeff)) {
          return true;
        }
      }
    }

    return false;
  }

  private checkBalance(leftCoeffs: number[], rightCoeffs: number[]): boolean {
    const allElements = this.getAllElements();

    for (const element of allElements) {
      let leftCount = 0;
      let rightCount = 0;

      // 计算左边的元素数量
      for (let i = 0; i < this._left.getFormulasCount(); i++) {
        const formula = this._left.getFormula(i);
        if (formula) {
          leftCount += leftCoeffs[i] * formula.getMolecularFormula().getElementCount(element);
        }
      }

      // 计算右边的元素数量
      for (let i = 0; i < this._right.getFormulasCount(); i++) {
        const formula = this._right.getFormula(i);
        if (formula) {
          rightCount += rightCoeffs[i] * formula.getMolecularFormula().getElementCount(element);
        }
      }

      if (leftCount !== rightCount) {
        return false;
      }
    }

    // 如果平衡成功，应用系数
    for (let i = 0; i < this._left.getFormulasCount(); i++) {
      const formula = this._left.getFormula(i);
      if (formula) {
        formula.setCount(leftCoeffs[i]);
      }
    }

    for (let i = 0; i < this._right.getFormulasCount(); i++) {
      const formula = this._right.getFormula(i);
      if (formula) {
        formula.setCount(rightCoeffs[i]);
      }
    }

    return true;
  }

  private getAllElements(): string[] {
    const elements: string[] = [];
    const leftElements = this._left.getElements();
    const rightElements = this._right.getElements();

    // 添加左边的元素
    for (const element of leftElements) {
      if (!elements.includes(element)) {
        elements.push(element);
      }
    }

    // 添加右边的元素
    for (const element of rightElements) {
      if (!elements.includes(element)) {
        elements.push(element);
      }
    }

    return elements;
  }

  print(): string {
    return `${this._left.getString()} = ${this._right.getString()}`;
  }

  // 重置所有系数为1
  reset(): void {
    for (let i = 0; i < this._left.getFormulasCount(); i++) {
      const formula = this._left.getFormula(i);
      if (formula) {
        formula.setCount(1);
      }
    }

    for (let i = 0; i < this._right.getFormulasCount(); i++) {
      const formula = this._right.getFormula(i);
      if (formula) {
        formula.setCount(1);
      }
    }
  }

  // 获取左边的字符串表示
  getLeftString(): string {
    return this._left.getString();
  }

  // 获取右边的字符串表示
  getRightString(): string {
    return this._right.getString();
  }
}